﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using YArchitech.Revit;
//using HYRevitCode.ElementSearchUtility.LinkDocumentSuite;
using HYRevitCode.ElementSearchUtility.LinkDocumentSuite;
using YJKRGeometry;

namespace LightSmokeTemperatureCameraAdjust
{
	internal class CeilingOrFloorSearcher
	{
		public List<CelingOrFloorStructure> GetCelingList()
		{
			return this.m_lstCeling;
		}

		public List<CelingOrFloorStructure> GetFloorList()
		{
			return this.m_lstFloor;
		}

		public CeilingOrFloorSearcher(Document doc)
		{
            this.GetCeilList(doc, this.m_lstCeling, (BuiltInCategory)(-2000038));
            this.GetCeilList(doc, this.m_lstFloor, (BuiltInCategory)(-2000032));
			this.m_lstCeling = (from c in this.m_lstCeling
			orderby c.m_dLevel
			select c).ToList<CelingOrFloorStructure>();
			this.m_lstFloor = (from c in this.m_lstFloor
			orderby c.m_dLevel
			select c).ToList<CelingOrFloorStructure>();
		}

		private List<CelingOrFloorStructure> GetCeilList(Document doc, List<CelingOrFloorStructure> lstCelingOrFloor, BuiltInCategory builtInCategory)
		{
			FilteredElementCollectorLinkDocument filteredElementCollectorLinkDocument = new FilteredElementCollectorLinkDocument(doc);
			CelingOrFloorStructure celingOrFloorStructure = new CelingOrFloorStructure();
			List<CelingOrFloorFaceInfo> list = new List<CelingOrFloorFaceInfo>();
			CelingOrFloorFaceInfo celingOrFloorFaceInfo = new CelingOrFloorFaceInfo();
			foreach (BaseLinkDocumentResultBean baseLinkDocumentResultBean in filteredElementCollectorLinkDocument.OfCategory(builtInCategory).WhereElementIsNotElementType().ToBeans())
			{
				celingOrFloorStructure = new CelingOrFloorStructure();
				celingOrFloorFaceInfo = new CelingOrFloorFaceInfo();
				list = new List<CelingOrFloorFaceInfo>();
				celingOrFloorFaceInfo.m_LinkInstance = baseLinkDocumentResultBean.UseLinkeInstance;
				celingOrFloorFaceInfo.m_face = this.GetLowerFace(baseLinkDocumentResultBean.UseElement);
				celingOrFloorFaceInfo.m_listFace = this.GetLowerFaces(baseLinkDocumentResultBean.UseElement);
				PlanarFace planarFace = celingOrFloorFaceInfo.m_face as PlanarFace;
				if (!(planarFace == null))
				{
					if (baseLinkDocumentResultBean.UseLinkeInstance != null)
					{
						celingOrFloorStructure.m_dLevel = planarFace.Origin.Z + LinkDocumentUtility.CalculateTransformEffectOnZ(baseLinkDocumentResultBean.UseLinkeInstance.GetTotalTransform());
					}
					else
					{
						celingOrFloorStructure.m_dLevel = planarFace.Origin.Z;
					}
					celingOrFloorFaceInfo.m_id = baseLinkDocumentResultBean.UseElement.Id;
					list.Add(celingOrFloorFaceInfo);
					celingOrFloorStructure.m_lstFaceInfo = list;
					bool flag = true;
					for (int i = 0; i < lstCelingOrFloor.Count; i++)
					{
						if (Geometry.IsEqual(lstCelingOrFloor[i].m_dLevel, celingOrFloorStructure.m_dLevel))
						{
							flag = false;
							lstCelingOrFloor[i].m_lstFaceInfo.Add(celingOrFloorFaceInfo);
						}
					}
					if (flag)
					{
						lstCelingOrFloor.Add(celingOrFloorStructure);
					}
				}
			}
			return lstCelingOrFloor;
		}

		private List<Face> GetLowerFaces(Element element)
		{
			List<Face> list = new List<Face>();
			Options options = new Options();
			options.ComputeReferences = true;
			foreach (GeometryObject geometryObject in new YJKElement(element).GetGeometry(options))
			{
				if (geometryObject is Solid)
				{
					foreach (object obj in (geometryObject as Solid).Faces)
					{
						PlanarFace planarFace = obj as PlanarFace;
						if (planarFace != null && planarFace.FaceNormal().Z < 0.0)
						{
							list.Add(planarFace);
						}
					}
				}
			}
			return list;
		}

		private Face GetLowerFace(Element element)
		{
			Face result = null;
			Options options = new Options();
			options.ComputeReferences = true;
			foreach (GeometryObject geometryObject in new YJKElement(element).GetGeometry(options))
			{
				if (geometryObject is Solid)
				{
					foreach (object obj in (geometryObject as Solid).Faces)
					{
						PlanarFace planarFace = obj as PlanarFace;
						if (planarFace != null && planarFace.FaceNormal().Z < 0.0)
						{
							result = planarFace;
							break;
						}
					}
				}
			}
			return result;
		}

		private List<CelingOrFloorStructure> m_lstCeling = new List<CelingOrFloorStructure>();

		private List<CelingOrFloorStructure> m_lstFloor = new List<CelingOrFloorStructure>();
	}
}
